/*
 * ip_camera_viewer.cpp
 *
 *  Created on: Oct 27, 2010
 *      Author: Alexey Brodkin
 */

#include "QFriendlyCameraViewer.h"
#include "QIpCamera.h"
#include <QDebug>
#include <QMouseEvent>
#include <QHostInfo>
#include <QNetworkInterface>
#include <QPaintDevice>
#include <QSignalMapper>

IPCameraViewer::IPCameraViewer(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    QString string;
    QString url;
    int value;
    bool ok;
    
    ui->setupUi(this);
    monitor_zoomed_number = 0;
    
    config_parser = new QConfigParser("QFriendlyCameraViewer.ini");
    
    string = config_parser->parameterValue("common", "monitoring_period");
    value = string.toInt(&ok, 10);
    if (ok)   
        intervals[VIEW_MODE_MONITOR] = value;
    else
        intervals[VIEW_MODE_MONITOR] = DEFAULT_PERIOD_MONITOR;
        

    string = config_parser->parameterValue("common", "zoomed_period");
    value = string.toInt(&ok, 10);
    if (ok)  
        intervals[VIEW_MODE_ZOOM] = value;
    else 
        intervals[VIEW_MODE_ZOOM] = DEFAULT_PERIOD_ZOOMED;

    init_camera(0, ui->lb_monitor_0);
    init_camera(1, ui->lb_monitor_1);
    init_camera(2, ui->lb_monitor_2);
    init_camera(3, ui->lb_monitor_3);
    
    delete config_parser;       
    
    zoom_widget = ui->lb_Zoom;
    zoom_widget->installEventFilter(this);
    
    QApplication::postEvent(zoom_widget, new QMouseEvent(QEvent::MouseButtonPress, QPoint(0, 0), Qt::LeftButton , Qt::LeftButton, Qt::NoModifier));
}

IPCameraViewer::~IPCameraViewer()
{
    for (int i=0; i<MONITORS_NUMBER; i++) {
        if (ip_camera[i]) {
            delete ip_camera[i];
            ip_camera[i] = NULL;
        }
    }

    delete ui;
}

void IPCameraViewer::init_camera(int number, QLabel * widget)
{
    QString string;
    QString url;
    
    ip_camera[number] = NULL;
    monitor_widget[number] = NULL;
    
    string = config_parser->parameterValue("camera_" + QString::number(number), "enabled");
    if (string.toLower() == QString("yes")) {
        url = config_parser->parameterValue("camera_" + QString::number(number), "url");
        if (!url.isEmpty()){
            ip_camera[number] = new QIpCamera(number, url);
            connect(ip_camera[number], SIGNAL(newImage(const int &, QPixmap)), this, SLOT(set_pixmap(const int &, QPixmap)));
            if (!ip_camera[number]->isInitialized()) {
                delete ip_camera[number];
                ip_camera[number] = NULL;                    
            }
            else {
                widget->installEventFilter(this);
                monitor_widget[number] = widget;
            }
        }    
    }
}

void IPCameraViewer::set_pixmap(int index, QPixmap pixmap)
{
    switch (mode) {
        case VIEW_MODE_MONITOR:
            if (monitor_widget[index])
                monitor_widget[index]->setPixmap(pixmap.scaled(320, 240, Qt::KeepAspectRatio, Qt::FastTransformation));
            break;

        case VIEW_MODE_ZOOM:
            if (index == monitor_zoomed_number) {
                zoom_widget->setPixmap(pixmap);
            }
            break;

        default:
            Q_ASSERT_X(0, "set_picture", "Unexpected view mode");
    }
}

bool IPCameraViewer::eventFilter(QObject *object, QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress) {
        for (int i=0; i<MONITORS_NUMBER; i++) {
            if (monitor_widget[i]) {
                if (object->objectName() == monitor_widget[i]->objectName()){
                    mode = VIEW_MODE_ZOOM;
                    monitor_zoomed_number = i;
                    ip_camera[i]->setPeriod(intervals[VIEW_MODE_ZOOM]);
                    ip_camera[i]->start();
                    zoom_widget->setPixmap((*monitor_widget[i]->pixmap()).scaled(640, 480, Qt::KeepAspectRatio, Qt::FastTransformation));
                    ui->stackedWidget->setCurrentWidget(ui->page_zoom);
                }
                else {
                    if (ip_camera[i]) {
                        ip_camera[i]->stop();
                    }
                }
            }
        }

        if (object->objectName() == zoom_widget->objectName()){
            mode = VIEW_MODE_MONITOR;
            for (int i=0; i<MONITORS_NUMBER; i++) {
                if (ip_camera[i]) {
                    ip_camera[i]->setPeriod(intervals[VIEW_MODE_MONITOR]);
                    ip_camera[i]->start();
                }
            }
            ui->stackedWidget->setCurrentWidget(ui->page_monitor);
        }

        return true;
    }

    // standard event processing
    return QObject::eventFilter(object, event);
}

QWidget * saved_widget;

void IPCameraViewer::on_pb_info_toggled()
{
    if (ui->pb_info->isChecked()){
        saved_widget = ui->stackedWidget->currentWidget();
        ui->stackedWidget->setCurrentWidget(ui->page_info);
        
        QHostInfo info = QHostInfo::fromName(QHostInfo::localHostName ());
        
        QString ips;

        // discover network interfaces and addressEntries 
        foreach( QNetworkInterface interface, QNetworkInterface::allInterfaces() ){
            foreach( QNetworkAddressEntry addressEntry, interface.addressEntries() ){
                QString address = QHostAddress( addressEntry.ip() ).toString();
                int dots = address.count(".");
                if (dots) {
                    ips += interface.name() + ": " + (addressEntry.ip()).toString() + "\n";
                }
            }
        }

        ui->l_info_ip->setText(ips);
        
#ifndef Q_WS_WIN
        // This code is strictly platform specific
        QFile file;
        QString cpu_average;
        QString memory;
        QString uptime;
        
        // Read average CPU load 
        file.setFileName("/proc/loadavg");
        if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            QTextStream in(&file);
            cpu_average = "CPU: " + in.readLine();
            file.close();                           
        }

        // Read memory params
        file.setFileName("/proc/meminfo");
        if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            QTextStream in(&file);
            memory = in.readLine() + "\n" + in.readLine();
            file.close();               
        }
        
        // Read system uptime
        file.setFileName("/proc/uptime");
        if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            QTextStream in(&file);
            float seconds_float = (((in.readLine()).split(" ")).first()).toFloat(NULL);
            int hours = abs(seconds_float / 60 / 60);
            int minutes = abs((seconds_float - hours * (60*60))/60);
            int seconds = abs(seconds_float - hours * (60*60) - minutes * 60);
            uptime = "Uptime: " + QString::number(hours, 10) + "h. " + QString::number(minutes, 10) + "m. "  + QString::number(seconds, 10) + "s.";
            file.close();               
        }
        
        ui->l_info_system->setText(cpu_average + "\n" + memory + "\n" + uptime);
        
//        qDebug() << "DPI-x" << QPaintDevice::physicalDpiX();
//        qDebug() << "DPI-y" << QPaintDevice::physicalDpiY();
#endif        

    }
    else {
        ui->stackedWidget->setCurrentWidget(saved_widget);
    }
    
}
